//
// Created by lucy on 1/18/2024.
//

#include "MutableArrayContainer.h"

template <typename E>
MutableArrayContainer<E>::MutableArrayContainer()
{
    len = 0;
    array = new E[0];
}

template <typename E>
MutableArrayContainer<E>::~MutableArrayContainer()
{
    if (array != nullptr)
    {
        delete array;
        array = nullptr;
    }
}

template <typename E>
int MutableArrayContainer<E>::length()
{
    return len;
}

template <typename E>
void MutableArrayContainer<E>::printError()
{
    std::cerr
        << "Wrong! The index entered is incorrect (the index cannot be less than 0, and the index cannot be greater than "
        << len - 1 << ")" << std::endl;
}

template <typename E>
bool MutableArrayContainer<E>::validIndex(int index)
{
    if (index < 0 || index >= len)
    {
        return false;
    }
    else
    {
        return true;
    }
}

template <typename E>
void MutableArrayContainer<E>::add(E ele)
{

    E *temp = new E[len + 1];
    for (int i = 0; i < len; i++)
    {
        temp[i] = array[i];
    }

    temp[len] = ele;
    len++;
    delete array;
    array = temp;
}

template <typename E>
void MutableArrayContainer<E>::add(int index, E ele)
{
    if (!this->validIndex(index))
    {
        //        std::cout << "Wrong! The input index is incorrect (the index cannot be less than 0)" << std::endl;
        printError();
        return;
    }

    E *temp = new E[len + 1];

    if (index >= len)
    {
        // 转移前面的元素
        for (int i = 0; i < len; i++)
        {
            temp[i] = array[i];
        }
        // 直接放在最后面
        temp[len] = ele;
    }
    else
    {
        // 转移前面的元素
        for (int i = 0; i < index; i++)
        {
            temp[i] = array[i];
        }
        // 放在中间的
        temp[index] = ele;
        for (int i = index; i < len; i++)
        {
            temp[i + 1] = array[i];
        }
    }
    len++;
    delete array;
    array = temp;
}

template <typename E>
E MutableArrayContainer<E>::remove(int index)
{
    if (!this->validIndex(index))
    {
        printError();
        return E{};
    }

    E ele = array[index];
    E *temp = new E[len - 1];

    for (int i = 0; i < index; i++)
    {
        temp[i] = array[i];
    }

    for (int i = index + 1; i < len; i++)
    {
        temp[i - 1] = array[i];
    }

    len--;
    delete array;
    array = temp;

    return ele;
}

template <typename E>
bool MutableArrayContainer<E>::removeElement(E ele)
{
    int index = this->index(ele);
    if (index == -1)
    {
        return false;
    }
    remove(index);
    return true;
}

template <typename E>
void MutableArrayContainer<E>::clear()
{
    delete array;
    array = new E[0];
    len = 0;
}

template <typename E>
E MutableArrayContainer<E>::set(int index, E ele)
{
    if (!this->validIndex(index))
    {
        printError();
        return E{};
    }
    E temp = array[index];
    array[index] = ele;
    return temp;
}

template <typename E>
E MutableArrayContainer<E>::get(int index)
{

    if (this->validIndex(index))
    {
        return array[index];
    }
    else
    {
        printError();
        return E{};
    }
}

template <typename E>
void MutableArrayContainer<E>::sort()
{
    for (int i = 0; i < len; i++)
    {
        int minIndex = i;
        for (int j = i + 1; j < len; j++)
        {
            if (array[j] < array[minIndex])
            {
                minIndex = j;
            }
        }
        if (minIndex != i)
        {
            E temp = array[minIndex];
            array[minIndex] = array[i];
            array[i] = temp;
        }
    }
}

template <typename E>
int MutableArrayContainer<E>::index(E ele)
{
    for (int i = 0; i < len; i++)
    {
        if (ele == array[i])
        {
            return i;
        }
    }
    return -1;
}

template <typename E>
std::string MutableArrayContainer<E>::str()
{
    if (len == 0)
    {
        return "[]";
    }
    std::ostringstream oss;
    oss << "[";
    for (int i = 0; i < len - 1; i++)
    {
        oss << array[i] << ", ";
    }

    oss << array[len - 1] << "]";
    return oss.str();
}
